package com.basker.pisces.domain.enums;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.basker.pisces.domain.value.meta.EnumType;
import com.basker.pisces.spring.SpringApplicationContext;

import lombok.extern.slf4j.Slf4j;

/**
 * 枚举类型元数据的管理器，通过所有的{@link IEnumTypeProvider}实例获取{@link EnumType}
 *
 * @author hangwen
 * @see IEnumTypeProvider
 * @see ResourceEnumTypeProvider
 */
@Slf4j
@Component
public class EnumTypeManager implements InitializingBean {

    public static EnumTypeManager getInstance() {
        return SpringApplicationContext.getInstance().getBean(EnumTypeManager.class);
    }

    @Autowired(required = false)
    private List<IEnumTypeProvider> providers;

    private Map<String/* name */, EnumType> enumTypeMap = null;

    @Override
    public void afterPropertiesSet() throws Exception {
        if (CollectionUtils.isEmpty(providers)) {
            return;
        }

        List<EnumType> enumTypes = providers.stream().map(p -> p.getEnumTypes())
                .filter(l -> !CollectionUtils.isEmpty(l)).flatMap(l -> l.stream()).collect(Collectors.toList());

        this.enumTypeMap = new LinkedHashMap<>(enumTypes.size(), 1);

        for (EnumType enumType : enumTypes) {
            if (this.enumTypeMap.put(enumType.getName(), enumType) != null) {
                log.error(EnumType.class.getName() + ":" + enumType.getName() + " is exist");
            }
        }
    }

    /**
     * 获取所有的枚举类型
     *
     * @return
     */
    public List<EnumType> getAllEnumTypes() {
        return new ArrayList<>(enumTypeMap.values());
    }

    /**
     * 根据名称获取指定的枚举类型
     *
     * @param ruleName
     * @return
     */
    public EnumType getEnumType(String name) {
        return enumTypeMap.get(name);
    }
}
